#ifndef __SG_PCL_READER_H__
#define __SG_PCL_READER_H__

#include "SGPCLJsonConfig.h"

#include <filesystem>
#include <string>

#include <pcl/io/obj_io.h>
#include <pcl/io/pcd_io.h>
#include <pcl/io/ply_io.h>

namespace sgpcl
{

/// <summary>
/// 点云文件读取算法参数(基于平均距离）
/// </summary>
struct SGReaderConfig : public SGPCLJsonConfig
{
  std::string strFileName; // 点云文件路径

  SGPCL_API SGReaderConfig();

  SGPCL_API ~SGReaderConfig() = default;

  /// <summary>
  /// 解析Json字符串，读取参数
  /// </summary>
  /// <param name="sJsonRoot">Json节点</param>
  SGPCL_API void ParseJson(const rapidjson::Value& sJsonRoot) final override;
};


template <typename PointT>
typename pcl::PointCloud<PointT>::Ptr ReadPCLFile(const std::filesystem::path& pathFileName)
{
  pcl::PointCloud<PointT>::Ptr spCloud(new pcl::PointCloud<PointT>());

  const std::string strExt = pathFileName.extension().string();

  int nRes = 0;
  // PCD格式
  if (strExt.find("pcd") != std::string::npos)
  {
    nRes = pcl::io::loadPCDFile(pathFileName.string(), *spCloud);
  }
  // obj格式
  else if (strExt.find("obj") != std::string::npos)
  {
    nRes = pcl::io::loadOBJFile(pathFileName.string(), *spCloud);
  }
  // ply格式
  else if (strExt.find("ply") != std::string::npos)
  {
    nRes = pcl::io::loadPLYFile(pathFileName.string(), *spCloud);
  }
  else // 未知文件格式
  {
    SG_PANIC("错误的文件格式：" + strExt);
  }

  if (nRes != 0)
  {
    SG_PANIC("打开文件错误!");
  }

  return spCloud;
}

/// <summary>
/// 读取点云文件，后期有更复杂的功能需求的话考虑写成类
/// </summary>
/// <param name="sConfig">点云文件读取参数</param>
template <typename PointT>
typename pcl::PointCloud<PointT>::Ptr ReadPCLFile(const SGReaderConfig& sConfig)
{
  // 计时器
  const std::string strTitle = "读取" + sConfig.strFileName + "文件...";
  SG_TIMER(strTitle);

  const std::filesystem::path pathInput(sConfig.strFileName);
  std::filesystem::path pathPCLFile;

  if (std::filesystem::is_directory(pathInput)) // 路径指向文件夹（无后缀名）
  {
    bool bPCLExisted = false;
    for (const std::filesystem::directory_entry& DirectoryIter :
      std::filesystem::recursive_directory_iterator(pathInput))
    {
      pathPCLFile = DirectoryIter.path();
      const std::filesystem::path strExt = pathPCLFile.extension();
      if (strExt == ".obj" || strExt == ".pcd" || strExt == ".ply")
      {
        bPCLExisted = true;
        break; // 只计算第一个
      }
    }
    if (!bPCLExisted) // 啥也魅友
    {
      SG_PANIC("找不到点云文件");
    }
  }
  else // 路径指向文件（有后缀名）
  {
    const std::filesystem::path strExt = pathInput.extension();
    pathPCLFile = pathInput;
  }


  return ReadPCLFile<PointT>(pathPCLFile);
}

}
#endif // !__SG_PCL_READER_H__
